<template>
  <w-dialog
    v-model="_value"
    closeFree
    title="扫码录入"
    width="500px"
    :showFooter="false"
    @closed="closeScan"
    @opened="openScan"
    v-if="pcMode"
  >
    <div class="scan-video" v-if="_value">
      <video ref="video" style="width: 100%" id="video" autoplay></video>
    </div>
    <p style="color: #656363; text-align: center">{{ tipMsg }}</p>
  </w-dialog>
  <popup v-else v-model:show="_value" :style="popupStyle" @closed="closeScan" @opened="openScan"
    position="left" lazy-render closeable safe-area-inset-bottom>
    <div class="scan-cancel" @click="_value = false">取消</div>
    <div class="m-scan-video" v-if="_value">
      <video ref="video" id="video" autoplay></video>
    </div>
    <p style="color: white; text-align: center">{{ tipMsg }}</p>
  </popup>
</template>

<script>
import { Popup } from 'vant'
import { $emit } from '/@/views/setting/workflow/utils/gogocodeTransfer'
import { BrowserMultiFormatReader } from '@zxing/library'
import { computed, onUnmounted, reactive, toRefs } from 'vue'

export default {
    name: 'ScanCode',
    components: { Popup },
    props: {
        modelValue: {
            type: Boolean,
            default: false,
        },
        pcMode: {
            type: Boolean,
            default: false,
        },
    },
    setup(props, context) {
        const { modelValue } = toRefs(props)
        const state = reactive({
            tipMsg: '',
            codeReader: null,
            popupStyle: {
                height: '100%',
                width: '100%',
                background: 'black',
                opacity: '0.8',
            },
        })
        const _value = computed({
            get: () => {
                return modelValue.value
            },
            set: val => {
                context.emit('update:modelValue', val)
            }
        })
        const closeScan = () => {
            if (state.codeReader) {
                state.codeReader.reset()
                state.codeReader = null
            }
        }
        const openScan = () => {
            if (!state.codeReader) {
                state.codeReader = new BrowserMultiFormatReader()
            }
            state.codeReader.getVideoInputDevices().then((videoInputDevices) => {
                state.tipMsg = '正在打开摄像头...'
                console.log('videoInputDevices', videoInputDevices)
                // 默认获取第一个摄像头设备id
                let firstDeviceId = videoInputDevices[0].deviceId
                // 获取第一个摄像头设备的名称
                const videoInputDeviceslablestr = JSON.stringify(
                    videoInputDevices[0].label
                )
                if (videoInputDevices.length > 1) {
                    // 判断是否后置摄像头
                    if (videoInputDeviceslablestr.indexOf('back') > -1) {
                        firstDeviceId = videoInputDevices[0].deviceId
                    } else {
                        firstDeviceId = videoInputDevices[1].deviceId
                    }
                }
                decodeFromInputVideoFunc(firstDeviceId)
            })
            .catch((err) => {
                state.tipMsg = '发生错误: ' + JSON.stringify(err)
            })
        }
        const decodeFromInputVideoFunc = (firstDeviceId) => {
            state.codeReader.reset() // 重置
            state.codeReader.decodeFromInputVideoDeviceContinuously(
                firstDeviceId,
                'video',
                (result, err) => {
                    state.tipMsg = '请将摄像头对准条形码/二维码...'
                    if (result) {
                        if (result.text) {
                            $emit('ok', result.text)
                            _value.value = false
                        }
                    }
                    if (err && !err) {
                        state.tipMsg = '识别失败: ' + JSON.stringify(err)
                    }
                }
            )
        }
        onUnmounted(() => {
            closeScan()
        })
        return {
            ...toRefs(state),
            _value,
            openScan,
            closeScan,
            decodeFromInputVideoFunc
        }
    }
}
</script>

<style lang="scss" scoped>
.scan-cancel {
  position: fixed;
  top: 20px;
  left: 20px;
  color: white;
  cursor: pointer;
  font-size: 1.1rem;
  opacity: 1;
}
.m-scan-video {
  width: 100%;
  text-align: center;
  margin-top: 40%;
  video {
    width: 80%;
  }
}
</style>